package com.yanqu.road.server.manger.config;

import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eSexType;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.player.UserTravel;
import com.yanqu.road.entity.travel.*;
import com.yanqu.road.logic.bussiness.config.TravelBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.entity.config.system.NormalWeightItem;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.enums.eTravelEventType;
import com.yanqu.road.entity.player.UserBeauty;
import com.yanqu.road.entity.servercenter.TitleInfo;
import com.yanqu.road.pb.activity.RecoveryRewardProto;
import com.yanqu.road.pb.assistant.AssistantProto;
import com.yanqu.road.pb.travel.TravelProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.BeautyModule;
import com.yanqu.road.server.gameplayer.module.player.ColdRoomModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.travel.TravelModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.*;

/**
 * 游历
 */
public class TravelMgr extends TempMgr {

	private static Logger logger = LogManager.getLogger(TravelMgr.class.getName());

	private static RandomHelper threadSafeRandom = new RandomHelper();

	private static List<TravelCity> travelCityList;

	private static Map<Integer, TravelEvent> travelEventMap;

	@Override
	public boolean stop() {
		return false;
	}

	@Override
	public boolean save() {
		return false;
	}

	@Override
	public boolean reloadConfig() {
		travelCityList = TravelBussiness.getTravelCityList();
		if(travelCityList.size() <= 0){
			return false;
		}
		travelEventMap = TravelBussiness.getTravelEventMap();
		if(travelEventMap.size() <= 0){
			return false;
		}
		return true;
	}

	@Override
	public boolean reloadData() throws Exception {
		return true;
	}

	@Override
	public boolean init() throws Exception {
		return reload();
	}

	public static TravelEvent getTravelEvent(int eventId) {
		return travelEventMap.get(eventId);
	}

	public static TravelCity getRandomTravelCity(int cityId){
		List<TravelCity> tempList = new ArrayList<>(travelCityList);
		for(TravelCity travelCity : tempList){
			if(travelCity.getCityId() == cityId) {
				tempList.remove(travelCity);
				break;
			}
		}
		int randomValue = threadSafeRandom.next(0, tempList.size());
		return tempList.get(randomValue);
	}

	public static TravelCity getTravelCity(int cityId){
		for(TravelCity travelCity : travelCityList){
			if(travelCity.getCityId() == cityId){
				return travelCity;
			}
		}
		return null;
	}

	public static List<Integer> getDiceValueList(int diceCount){
		List<Integer> dataList = new ArrayList<>();
		for(int i = 0; i < diceCount; i++){
			int randomValue = threadSafeRandom.next(1, 7);
			dataList.add(randomValue);
		}
		return dataList;
	}

	/**
	 * 出稳赢的骰子
	 */
	public static List<Integer> getWinDiceValueList(int diceCount, int casinoValue){
		List<Integer> dataList = new ArrayList<>();
		for(int i = 0; i < casinoValue; i++){
			int randomValue = threadSafeRandom.next(4, 7);
			dataList.add(randomValue);
		}
		for(int i = 0; i < diceCount - casinoValue; i++){
			int randomValue = threadSafeRandom.next(1, 4);
			dataList.add(randomValue);
		}
		return dataList;
	}

	public static boolean isCasinoWin(List<Integer> diceList, int casinoValue){
		int value = 0;
		for(int temp : diceList){
			if(temp > 3){
				value++;
			}
		}
		return value == casinoValue;
	}

//	public static TravelEvent getCityTravelEvent(GamePlayer player, TravelCity travelCity){
//		int totalWeight = 0;
//		List<NormalWeightItem> weightList = new ArrayList<>();
//		BeautyModule beautyModule = player.getModule(BeautyModule.class);
//		for(NormalWeightItem eventWeight : travelCity.getBeautyEventWeightList()){
//			TravelEvent travelEvent = getTravelEvent(eventWeight.getValue().intValue());
//			if(travelEvent.getEventType() == eTravelEventType.HasBeautyEvent.getValue() || travelEvent.getEventType() == eTravelEventType.BeautyEvent.getValue()){
//				int beautyId = 0;
//				for(Map.Entry<Integer, BigInteger> dataEntry : travelEvent.getReward().getGoods().entrySet()){
//					beautyId = dataEntry.getKey();
//					break;
//				}
//				if(beautyId != 0){
//					if(GoodsMgr.isBeautyGoods(beautyId)) {
//						if(travelEvent.getEventType() == eTravelEventType.HasBeautyEvent.getValue()) {
//							UserBeauty userBeauty = beautyModule.getUserBeauty(beautyId);
//							if (BeautyMgr.isUserBeautyExist(userBeauty) && player.getModule(ColdRoomModule.class).isBeautyFree(beautyId)) {//拥有美女且没派到冷宫
//								weightList.add(eventWeight);
//								totalWeight += eventWeight.getWeight();
//							}
//						}else {
//							if (player.getModule(ColdRoomModule.class).isBeautyFree(beautyId)) {//没派到冷宫
//								weightList.add(eventWeight);
//								totalWeight += eventWeight.getWeight();
//							}
//						}
//					}
//				}
//			}else {
//				weightList.add(eventWeight);
//				totalWeight += eventWeight.getWeight();
//			}
//		}
//		boolean isNormalEvent = false;
//		if(weightList.size() > 0){
//			int randomValue = threadSafeRandom.next(0, 1000);
//			if(travelCity.getBeautyWeight() <= randomValue){//非美女事件
//				isNormalEvent = true;
//			}
//		}else {
//			isNormalEvent = true;
//		}
//		if(isNormalEvent){
//			totalWeight = 0;
//			for(NormalWeightItem eventWeight : travelCity.getNormalEventWeightList()){
//				totalWeight += eventWeight.getWeight();
//			}
//			weightList = travelCity.getNormalEventWeightList();
//		}
//		int randomWeight = threadSafeRandom.next(0, totalWeight);
//		int tempWeight = 0;
//		for (NormalWeightItem eventWeight : weightList) {
//			tempWeight += eventWeight.getWeight();
//			if (tempWeight >= randomWeight) {
//				return getTravelEvent(eventWeight.getValue().intValue());
//			}
//		}
//		return null;
//	}

	public static TravelEvent getCityTravelEvent(GamePlayer player, TravelCity travelCity){
		int totalWeight = 0;
		List<NormalWeightItem> weightList = new ArrayList<>();
		BeautyModule beautyModule = player.getModule(BeautyModule.class);
		TravelModule travelModule = player.getModule(TravelModule.class);
		for(NormalWeightItem eventWeight : getEventWeightList(travelModule.getUserTravel(), travelCity.getBeautyEventWeightList())){
			TravelEvent travelEvent = getTravelEvent(eventWeight.getValue().intValue());
			if(travelEvent.getEventType() == eTravelEventType.HasBeautyEvent.getValue() || travelEvent.getEventType() == eTravelEventType.BeautyEvent.getValue()){
				int beautyId = 0;
				for(Map.Entry<Integer, BigInteger> dataEntry : travelEvent.getReward().getGoods().entrySet()){
					beautyId = dataEntry.getKey();
					break;
				}
				if(beautyId != 0){
					if(GoodsMgr.isBeautyGoods(beautyId)) {
						if(travelEvent.getEventType() == eTravelEventType.HasBeautyEvent.getValue()) {
							UserBeauty userBeauty = beautyModule.getUserBeauty(beautyId);
							if (BeautyMgr.isUserBeautyExist(userBeauty) && player.getModule(ColdRoomModule.class).isBeautyFree(beautyId)) {//拥有美女且没派到冷宫
								if(checkBeautyCanEncounter(player, beautyId)) {
									weightList.add(eventWeight);
									totalWeight += eventWeight.getWeight();
								}
							}
						}else {
							if (player.getModule(ColdRoomModule.class).isBeautyFree(beautyId)) {//没派到冷宫
								if(checkBeautyCanEncounter(player, beautyId)) {
									weightList.add(eventWeight);
									totalWeight += eventWeight.getWeight();
								}
							}
						}
					}
				}
			}else {
				weightList.add(eventWeight);
				totalWeight += eventWeight.getWeight();
			}
		}
		boolean isNormalEvent = false;
		if(weightList.size() > 0){
			int randomValue = threadSafeRandom.next(0, 1000);
			if(travelCity.getBeautyWeight() <= randomValue){//非美女事件
				isNormalEvent = true;
			}
		}else {
			isNormalEvent = true;
		}
		if(isNormalEvent){
			totalWeight = 0;
			List<NormalWeightItem> tempList = getEventWeightList(travelModule.getUserTravel(), travelCity.getNormalEventWeightList());
			for(NormalWeightItem eventWeight : tempList){
				totalWeight += eventWeight.getWeight();
			}
			weightList = tempList;
		}
		int randomWeight = threadSafeRandom.next(0, totalWeight);
		int tempWeight = 0;
		for (NormalWeightItem eventWeight : weightList) {
			tempWeight += eventWeight.getWeight();
			if (tempWeight >= randomWeight) {
				return getTravelEvent(eventWeight.getValue().intValue());
			}
		}
		return null;
	}

	/**
	 * 美女能否偶遇（主要是养蚕女跟贵公子处理）
	 */
	public static boolean checkBeautyCanEncounter(GamePlayer player, int beautyId){
		//未配置，不可偶遇
		if(BeautyMgr.getBeautyInfo(beautyId) == null){
			return false;
		}
		//后台屏蔽，不可偶遇
		if (!HideGoodsMgr.getHideGoods().contains(beautyId)) {
			return false;
		}

		if(beautyId == GameConfig.BEAUTY_ID_SILKWORM){//养蚕女
			if(player.getUserInfo().getSex() == eSexType.FEMALE.getValue()){//女性角色
				UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(beautyId);
				return BeautyMgr.isUserBeautyExist(userBeauty);          //女性角色已经拥有养蚕女才能遇到
			}
		}else if(beautyId == GameConfig.BEAUTY_ID_CHILDE){//贵公子
			if(player.getUserInfo().getSex() == eSexType.MALE.getValue()){//男性角色
				UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(beautyId);
				return BeautyMgr.isUserBeautyExist(userBeauty);           //男性角色已经拥有贵公子才能遇到
			}else {//女性玩家
				UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(GameConfig.BEAUTY_ID_SILKWORM);
				if(BeautyMgr.isUserBeautyExist(userBeauty)){//已经有养蚕女了，不能再遇到贵公子了
					return false;
				}
			}
		}
		return true;
	}

	public static List<NormalWeightItem> getEventWeightList(UserTravel userTravel, List<NormalWeightItem> weightItemList) {
		List<NormalWeightItem> dataList = new ArrayList<>();
		for(NormalWeightItem eventWeight : weightItemList) {
			TravelEvent travelEvent = getTravelEvent(eventWeight.getValue().intValue());
			NormalWeightItem weightItem = eventWeight.clone();
			if(travelEvent.isNeedCalc()){
				double times = 0;
				if(null != userTravel){
					String[] arr = travelEvent.getParamStr().split("\\|");
					if (arr.length == 2) {
						times = userTravel.getTravelEventTimes(travelEvent.getId());
					}else {
						times = userTravel.getTodayEventTimes(travelEvent.getId());
					}
				}
				double weight = weightItem.getWeight();
				weight = weight * (1 - (times /(times + travelEvent.getParam1()) * ((double) travelEvent.getParam2() / 1000)));
				weightItem.setWeight((int) Math.ceil(weight));
			}
			dataList.add(weightItem);
		}
		return dataList;
	}

	public static Property getPrestigeReward(GamePlayer player){
		int skillAddition = player.getModule(BeautyModule.class).getIdentitySkillAddition(eSkillType.TravelAddPrestige.getValue(), 0);
		Property reward = new Property();
		reward.addProperty(GameConfig.GAME_MONEY_PRESTIGE, BigInteger.valueOf(GameConfig.TRAVEL_ADD_PRESTIGE + skillAddition));
		reward.addProperty(GameConfig.GAME_MONEY_PRESTIGE, BigInteger.valueOf(CurioMgr.getSkillAdditionBySkillType(eSkillType.CurioTravelPrestigeAddSkill.getValue(), player, 0)));
		return reward;
	}

	public static int getMaxTravelPower(int titleId){
		TitleInfo titleInfo = TitleMgr.getTitleInfo(titleId);
		return titleInfo.getTravelPowerTimes();
	}

	public static boolean canTravelAll(GamePlayer player){
		return player.getTitleId() >= ConfigMgr.getTravelMultiNeedTitle();
	}


	/**
	 * 一键使用游历
	 * 游历设置
	 * 	开启游历开关后，自动进行游历
	 * 	直到体力不足
	 * 自动设置
	 * 	月老自动选择亲密度最高美女
	 * 	骰子默认选择第3当，第一个选项
	 * 	用餐自动选择赚钱最高
	 * 	共饮事件
	 * 		自动使用5元宝，参加共饮事件
	 * 		元宝不足则自动选择不参加
	 * 	观音事件
	 * 		自动完成
	 * 	财神事件
	 * 		自动完成
	 * 手动设置
	 * 	妙音坊
	 * 		可进行以下选项选择
	 * 			默认随机选择美女
	 * 			也可以指定选择对应美女
	 * 		选项自动选择寒暄
	 */
	public static AssistantProto.AssistantTravelGoRespMsg.Builder oneKeyTravel(GamePlayer player, int beautyId){
		AssistantProto.AssistantTravelGoRespMsg.Builder builder = AssistantProto.AssistantTravelGoRespMsg.newBuilder();
		TravelModule travelModule = player.getModule(TravelModule.class);
		if(null == travelModule.getUserTravel()){
			builder.setRet(GameErrorCode.E_TRAVEL_IS_LOCK);
			return builder;
		}
		//真实游历次数
		int realTravelTime = 0;
		travelModule.calcPower();

		if (travelModule.getUserTravel().getPower() <= 0) {
			builder.setRet(GameErrorCode.E_TRAVEL_POWER_NO_ENOUGH);
//			player.notifyListener(eGamePlayerEventType.RechargeTravelNew.getValue(), 0);//6.4.0优化，小玉不触发现金礼包
			return builder;
		}
		TravelResult finalResult = null;
		while (travelModule.getUserTravel().getPower() > 0 && realTravelTime < GameConfig.ASSISTANT_TRAVEL_MAX_TIMES) {
			int times = Math.min(GameConfig.ASSISTANT_TRAVEL_MAX_TIMES - realTravelTime, travelModule.getUserTravel().getPower());
			TravelResult travelResult = travelModule.batchTravel(times,true);
			//第一次进来
			if (finalResult == null) {
				//报错直接弹出
				if (travelResult.getRet() != 0) {
					builder.setRet(travelResult.getRet());
					return builder;
				}
				finalResult = travelResult;
				realTravelTime = travelResult.getTravelGainList().size();
			} else {
				//之前成功游历过 后面没次数或者其他问题则弹出循环
				if (travelResult.getRet() != 0) {
					break;
				}
				//汇总所有游历结果
				finalResult.getTravelGainList().addAll(travelResult.getTravelGainList());
				realTravelTime += travelResult.getTravelGainList().size();
			}

			// 自动处理特殊事件
			List<TravelSelectObjectResult> eventList = autoDealEvent(player, travelModule, beautyId);
			for (TravelSelectObjectResult item : eventList) {
				TravelProto.TravelSelectObjectRespMsg.Builder respMsg = TravelProto.TravelSelectObjectRespMsg.newBuilder();
				respMsg.setRet(item.getRet());
				respMsg.setEventId(item.getEventId());
				respMsg.setObjectId(item.getObjectId());
				respMsg.setAddValue(item.getAddValue());
				if (!item.getConsume().isNothing()) {
					respMsg.setConsume(PropertyHelper.parsePropertyToString(item.getConsume()));
				}
				builder.addSelectObjectList(respMsg);
			}
		}

		UserTravel userTravel = player.getModule(TravelModule.class).getUserTravel();
		if (userTravel.getPower() <= 0) {
//			player.notifyListener(eGamePlayerEventType.RechargeTravelNew.getValue(), 0);//6.4.0优化，小玉不触发现金礼包
		}
        if (finalResult == null) {
            finalResult = new TravelResult();
            finalResult.setRet(GameErrorCode.E_TRAVEL_POWER_NO_ENOUGH);
        }
		builder.setRet(finalResult.getRet());
		for (TravelGain travelGain : finalResult.getTravelGainList()) {
			builder.addEventIdList(travelGain.getEventId());
		}
		builder.addAllEventIdList(userTravel.getEventIdList());
		builder.setCityId(userTravel.getCityId());
		return builder;
	}

	/**
	 * 找回的游历
	 */
	public static RecoveryRewardProto.RecoverTravelGoRespMsg.Builder recoveryTravel(GamePlayer player, int times,int beautyId) {
		RecoveryRewardProto.RecoverTravelGoRespMsg.Builder builder = RecoveryRewardProto.RecoverTravelGoRespMsg.newBuilder();
		TravelModule travelModule = player.getModule(TravelModule.class);
		if (null == travelModule.getUserTravel()) {
			builder.setRet(GameErrorCode.E_TRAVEL_IS_LOCK);
			return builder;
		}
		travelModule.addPower(times);
		TravelResult travelResult = travelModule.batchTravel(times, false);
		if (travelResult.getRet() != 0) {
			builder.setRet(travelResult.getRet());
			return builder;
		}
		List<TravelSelectObjectResult> eventList = autoDealEvent(player, travelModule, beautyId);
		for (TravelSelectObjectResult item : eventList) {
			TravelProto.TravelSelectObjectRespMsg.Builder respMsg = TravelProto.TravelSelectObjectRespMsg.newBuilder();
			respMsg.setRet(item.getRet());
			respMsg.setEventId(item.getEventId());
			respMsg.setObjectId(item.getObjectId());
			respMsg.setAddValue(item.getAddValue());
			if (!item.getConsume().isNothing()) {
				respMsg.setConsume(PropertyHelper.parsePropertyToString(item.getConsume()));
			}
			builder.addSelectObjectList(respMsg);
		}
		builder.setRet(travelResult.getRet());
		for (TravelGain travelGain : travelResult.getTravelGainList()) {
			builder.addEventIdList(travelGain.getEventId());
		}
		UserTravel userTravel = player.getModule(TravelModule.class).getUserTravel();
		builder.addAllEventIdList(userTravel.getEventIdList());
		builder.setCityId(userTravel.getCityId());
		return builder;

	}

	/**
	 * 自动处理特殊事件
	 * @param player
	 * @param travelModule
	 * @param beautyId
	 */
	public static List<TravelSelectObjectResult> autoDealEvent(GamePlayer player,TravelModule travelModule, int beautyId){
		Random random = new Random();
		// 自动处理特殊事件
		List<TravelSelectObjectResult> listResult = new ArrayList<>();
		LinkedList<Integer> list = new LinkedList<>(travelModule.getUserTravel().getEventIdList());
		for (int eventId : list){
			TravelEvent travelEvent = TravelMgr.getTravelEvent(eventId);
			TravelProto.TravelSelectObjectRespMsg.Builder respMsg = TravelProto.TravelSelectObjectRespMsg.newBuilder();
			TravelSelectObjectResult selectObjectResult ;
			if(travelEvent.getEventType() == eTravelEventType.BrothelEvent.getValue()){
				// 妙音坊/青楼
				int objectId = beautyId;
				if(!ConfigMgr.getBrothelBeautyList().contains(beautyId)){
					//  随机美女 并选择免费的
					objectId = ConfigMgr.getBrothelBeautyList().get(random.nextInt(ConfigMgr.getBrothelBeautyList().size()));
				}
				travelModule.selectBrothelBeauty(travelEvent, objectId);
				selectObjectResult = travelModule.selectBrothelInteractiveType(travelEvent, ConfigMgr.getBrothelFreeType());
			}else if(travelEvent.getEventType() == eTravelEventType.DrinkEvent.getValue()){
				// 共饮事件自动使用5元宝，参加共饮事件 元宝不足则自动选择不参加
				Property consume = new Property(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(GameConfig.DRINK_INTERACTIVE_COST));
				int isDrink = 0;
				if (player.getModule(CurrencyModule.class).currencyIsEnough(consume)) {
					isDrink = 1;
				}
				selectObjectResult = travelModule.selectIsDrink(travelEvent, isDrink);
			}else if(travelEvent.getEventType() == eTravelEventType.AppointTrystEvent.getValue()){
				// 月老自动选择亲密度最高美女
				UserBeauty userBeauty = player.getModule(BeautyModule.class).getMaxIntimacyUserBeauty();
				selectObjectResult = travelModule.selectTrystBeauty(travelEvent, userBeauty.getBeautyId(),1);
			}else if(travelEvent.getEventType() == eTravelEventType.CasinoEvent.getValue()){
				// 骰子默认第三个选项 随便大小
				travelModule.selectCasinoType(travelEvent, ConfigMgr.getBestRewardCasinoInteractiveType());
				selectObjectResult = travelModule.selectCasinoValue(travelEvent, 1);
			}else if(travelEvent.getEventType() == eTravelEventType.PatronsWineEvent.getValue()){
				// 用餐自动选择赚钱最高
				UserPatrons userPatrons = player.getModule(PatronsModule.class).getMaxEarnPatrons();
				selectObjectResult = travelModule.selectWinePatrons(travelEvent, userPatrons.getPatronsId(),1);
			}else {
				logger.error("autoDealEvent 存在未定义的特殊事件id:{}",travelEvent.getEventType());
				continue;
			}
			respMsg.setRet(selectObjectResult.getRet());
			respMsg.setEventId(selectObjectResult.getEventId());
			respMsg.setObjectId(selectObjectResult.getObjectId());
			respMsg.setAddValue(selectObjectResult.getAddValue());
			listResult.add(selectObjectResult);
		}
		travelModule.getUserTravel().getEventIdList().clear();
		// 同步游历信息
		travelModule.syncUserTravel();
		return listResult;
	}


}
